#pragma once

#include "hdmap/HDMapExports.hpp"
#include "hdmap/HDMapCommon.hpp"
#include "hdmap/SpeedLimit.hpp"
#include "hdmap/Road.hpp"


namespace Navinfo
{
	namespace Engine
	{
		struct ProhibitedRange {
			bool  prohibited;
			HDMapGeometryRangeReference range;
		};

		/**
		 *  @brief Lane infomation
		 */
		class HDMAP_API_PUBLIC HDMapLaneInfo
		{
		public:
			friend class HDMapImpl;
			HDMapLaneInfo() = default;
			HDMapLaneInfo(DataSource::NDSLane &ndsLane);
			virtual ~HDMapLaneInfo() = default;

		public:
			/**
			 *  @brief Get lane ID
			 *  @return Lane ID
			 */
			const uint64_t	GetID() const { return m_nID; }
			/**
			 *  @brief Get the tile ID where the lane is located
			 *  @return Tile ID
			 */
			const uint32_t	GetTileID() const { return m_nTileID; }
			/**
			 *  @brief get lane width of the lane,unit cm
			 *  @return lane width 
			 */
			const uint32_t GetWidth() const{ return m_nWidth; }
			/**
			 *  @brief get lane percent width of the lane,unit cm
			 *  @return percent width info of lane
			 */
			const std::vector<HDMapLaneWidthInfo> GetPercentWidth() const{ return m_vtPercentWidth; }
			/**
			 *  @brief get lane num of the lane's sequence, from right to left along the lane's direction, e.g. Num 0,1,....N
			 *  @return order num
			 */
			const uint16_t GetOrderNum() const { return m_nOrderNum; }
			/**
			 *  @brief get connectivity type of the lane
			 *  @return Connectivity type
			 */
			HDMapLaneConnectivityElementType GetConnectivityElemType() const { return m_ConnectivityElemType; }
			/**
			 *  @brief get right side lane of this lane
			 *  @return right side lane
			 */
			const std::shared_ptr<HDMapLaneInfo> GetRightLane() const { return m_ptrRightLane.lock(); }
			/**
			 *  @brief get left side lane of this lane
			 *  @return left side lane
			 */
			const std::shared_ptr<HDMapLaneInfo> GetLeftLane() const { return m_ptrLeftLane.lock(); }
			/**
			 *  @brief get opposite lane of this lane with same reference link which  has only one lane on both direction
			 *  @return opposite lane
			 */
			const std::vector<std::weak_ptr<HDMapLaneInfo>>& GetOppositeLanes() const { return m_vtOppositeLanes; }
			/**
			 *  @brief Get the shape point coordinate list of the lane
			 *  @return a list of shape point coordinate
			 */
			const std::vector<Navinfo::Engine::Math::Vec3d>& GetGeometryPoints() const { return m_vtGeometryPoints; }
			
			/**
			 *  @brief Get a list of all source lane
			 *  @return a list of all source lane
			 */
			const std::vector<std::weak_ptr<HDMapLaneInfo>>& GetSourceLanes() const { return m_vtSourceLanes; }
			/**
			 *  @brief Get a list of all destination lane
			 *  @return a list of all destination lane
			 */
			const std::vector<std::weak_ptr<HDMapLaneInfo>>& GetDestinationLanes() const { return m_vtDestinationLanes; }
			/**
			 *  @brief get right side lane boundary
			 *  @return right lane boundary
			 */
			const std::shared_ptr<HDMapLaneBoundariesInfo> GetRightLaneBoundaries() const { return m_ptrRightLaneBoundaries; }
			/**
			 *  @brief get left side lane boundary
			 *  @return left lane boundary
			 */
			const std::shared_ptr<HDMapLaneBoundariesInfo> GetLeftLaneBoundaries() const { return m_ptrLeftLaneBoundaries; }
		
			/**
			 *  @brief get road for the lane belong
			 *  @return road infomation
			 */
			const std::shared_ptr<HDMapRoadInfo> GetRoad() const { return m_ptrRoad.lock(); }

			/**
			 *  @brief get reference lane group of the lane 
			 *  @return lane group infomation
			 */
			const std::shared_ptr<HDMapLaneGroupInfo> GetLaneGroup() const { return m_ptrLaneGroup.lock(); }

			/**
			 *  @brief get direction  for the lane
			 */
			const HDMapDirection GetDirection() const { return m_Direction; }

			/**
			 *  @brief query whether the lane is virtual lane on intersection
			 */
			const bool IsNonMotorizedLane() const { return m_bNonMotorizedLane; }

			/**
			 *  @brief Query vehicle is restricted or not
			 */
			bool IsRestrict(HDMapVehicleTypes vtype, DayOfYear curDayOfYear, DayOfWeekBitPos curDayOfWeek, TimeOfDay curTimeOfDay, std::vector<ProhibitedRange>  &outVtRanges) const
			{
				outVtRanges.clear();
				if (mVecAccessCondition.empty())
				{
					ProhibitedRange item;
					item.range.dRangeStartPos = 0;
					item.range.dRangeEndPos = 100;
					item.range.geometryReferenceType = HDMapGeometryRangeReference::LaneGeometry;
					item.prohibited = false;
					outVtRanges.push_back(item);
					return false;
				}

				auto getFullRange = [](const HDMapGeometryRangeReference &range, const double &roadLength)->ProhibitedRange {
					ProhibitedRange ret;
					ret.range.geometryReferenceType = range.geometryReferenceType;
					if (range.geometryReferenceType == HDMapGeometryRangeReference::RoadGeometry) {
						ret.range.dRangeStartPos = int(range.dRangeStartPos * 10000 / roadLength) / 100.0;
						ret.range.dRangeEndPos = int(range.dRangeEndPos * 10000 / roadLength) / 100.0;
					}
					else {
						ret.range.dRangeStartPos = 0;
						ret.range.dRangeEndPos = 100;
					}
					return ret;
				};

				bool bRet = false;
				for (auto &it : mVecAccessCondition) {
					if (it.dateRangeOfYear_valid_flag) {
						if (it.dateRangeOfYear.IsInRange(curDayOfYear)) {
							if (isVehicle(it.vehicleType, vtype)) {
								if (it.mProhibleRange.prohibited) {
									ProhibitedRange item = it.mProhibleRange;
									item.prohibited = true;
									outVtRanges.push_back(item);
									bRet = bRet || true;
								}
								else {
									ProhibitedRange item = getFullRange(m_LaneGeometryReference, m_RoadLaneght);
									item.prohibited = true;
									outVtRanges.push_back(item);
									bRet = bRet || false;
									return true;
								}
							}
							else {
								if (it.mProhibleRange.prohibited) {
									ProhibitedRange item = it.mProhibleRange;
									item.prohibited = false;
									outVtRanges.push_back(item);
									bRet = bRet || false;
								}
								else {
									ProhibitedRange item = getFullRange(m_LaneGeometryReference, m_RoadLaneght);
									item.prohibited = false;
									outVtRanges.push_back(item);
									return false;
								}
							}
						}
					}
				}
				bRet = bRet || IsRestrict(vtype, curDayOfWeek, curTimeOfDay, outVtRanges);

				auto IsSideInRange = [](const ProhibitedRange&range, double val)->bool {
					if (range.range.dRangeStartPos <= val && val <= range.range.dRangeEndPos) {
						return true;
					}
					return false;
				};
				auto IsRangeConn = [&IsSideInRange](const ProhibitedRange &a, const ProhibitedRange &b)->bool {
					if (IsSideInRange(a, b.range.dRangeStartPos))
					{
						return true;
					}
					if (IsSideInRange(a, b.range.dRangeEndPos))
					{
						return true;
					}
					if (IsSideInRange(b, a.range.dRangeStartPos))
					{
						return true;
					}
					if (IsSideInRange(b, a.range.dRangeEndPos))
					{
						return true;
					}
					return false;
				};

				auto mergeRange = [](const ProhibitedRange &a, const ProhibitedRange &b)->ProhibitedRange {
					ProhibitedRange ret = a;
					if (b.range.dRangeStartPos < ret.range.dRangeStartPos)
					{
						ret.range.dRangeStartPos = b.range.dRangeStartPos;
					}
					if (b.range.dRangeEndPos > ret.range.dRangeEndPos)
					{
						ret.range.dRangeEndPos = b.range.dRangeEndPos;
					}
					return ret;
				};

				auto mergeProhibitedRange = [&IsRangeConn, &mergeRange](
					std::vector<ProhibitedRange> outVtRanges,
					bool bProhiblted,
					std::vector<ProhibitedRange> &finished_vt_ranges
					)->void {
					while (!outVtRanges.empty()) {
						ProhibitedRange range = *outVtRanges.begin();
						outVtRanges.erase(outVtRanges.begin());
						if (range.prohibited != bProhiblted) {
							continue;
						}
						bool Inserted = false;
						for (auto it_f = finished_vt_ranges.begin(); it_f != finished_vt_ranges.end(); it_f++)
						{
							if (IsRangeConn(*it_f, range))
							{
								outVtRanges.push_back(mergeRange(*it_f, range));
								Inserted = true;
								finished_vt_ranges.erase(it_f);
								break;
							}
						}
						if (!Inserted)
						{
							finished_vt_ranges.push_back(range);
						}
					}
				};

				std::vector<ProhibitedRange>  vtProhibltedRanges;
				std::vector<ProhibitedRange>  vtNoProhibltedRanges;
				mergeProhibitedRange(outVtRanges, true, vtProhibltedRanges);
				mergeProhibitedRange(outVtRanges, false, vtNoProhibltedRanges);

				auto remove_range = [&IsSideInRange, &IsRangeConn](
					const ProhibitedRange &range,
					const ProhibitedRange &removeRange,
					std::vector<ProhibitedRange> &result
					)->bool
				{
					if (!IsRangeConn(range, removeRange)) {
						return false;
					}
					ProhibitedRange union_range = range;
					if (removeRange.range.dRangeStartPos < union_range.range.dRangeStartPos) {
						union_range.range.dRangeStartPos = removeRange.range.dRangeStartPos;
					}
					if (removeRange.range.dRangeEndPos > union_range.range.dRangeEndPos) {
						union_range.range.dRangeEndPos = removeRange.range.dRangeEndPos;
					}
					if (removeRange.range.dRangeStartPos > union_range.range.dRangeStartPos)
					{
						ProhibitedRange tmp = range;
						tmp.range.dRangeStartPos = union_range.range.dRangeStartPos;
						tmp.range.dRangeEndPos = removeRange.range.dRangeStartPos;
						result.push_back(tmp);
						if (removeRange.range.dRangeEndPos < union_range.range.dRangeEndPos)
						{
							ProhibitedRange tmp2 = range;
							tmp2.range.dRangeStartPos = removeRange.range.dRangeEndPos;
							tmp2.range.dRangeEndPos = union_range.range.dRangeEndPos;
							result.push_back(tmp2);
						}
						return true;
					}
					else
					{
						assert(removeRange.range.dRangeStartPos == union_range.range.dRangeStartPos);
						if (removeRange.range.dRangeEndPos < union_range.range.dRangeEndPos)
						{
							ProhibitedRange tmp = range;
							tmp.range.dRangeStartPos = removeRange.range.dRangeEndPos;
							tmp.range.dRangeEndPos = union_range.range.dRangeEndPos;
							result.push_back(tmp);
							return true;
						}
						else
						{
							return true;
						}
					}

				};

				if (!vtProhibltedRanges.empty() && !vtNoProhibltedRanges.empty())
				{
					std::vector<ProhibitedRange>  vtNoProhibltedRanges_left;
					for (auto &it_no_prohible : vtNoProhibltedRanges) {
						for (auto &it_prohible : vtProhibltedRanges)
						{
							remove_range(it_no_prohible, it_prohible, vtNoProhibltedRanges_left);
						}
					}
					vtNoProhibltedRanges = std::move(vtNoProhibltedRanges_left);
				}

				std::vector<ProhibitedRange> complement_ranges;
				if (!vtProhibltedRanges.empty())
				{
					ProhibitedRange range_begin = getFullRange(m_LaneGeometryReference, m_RoadLaneght);
					range_begin.prohibited = false;
					complement_ranges.push_back(range_begin);

					for (auto &it : vtProhibltedRanges) {
						for (auto it_complement = complement_ranges.begin();
							it_complement != complement_ranges.end();
							it_complement++)
						{
							std::vector<ProhibitedRange> resultRange;
							if (remove_range(*it_complement, it, resultRange)) {
								complement_ranges.erase(it_complement);
								complement_ranges.insert(complement_ranges.end(), resultRange.begin(), resultRange.end());
								break;
							}
						}
					}
					complement_ranges.insert(complement_ranges.end(), vtNoProhibltedRanges.begin(), vtNoProhibltedRanges.end());
					vtNoProhibltedRanges.clear();
					mergeProhibitedRange(complement_ranges, false, vtNoProhibltedRanges);

					outVtRanges.clear();
					outVtRanges = vtProhibltedRanges;
					outVtRanges.insert(outVtRanges.end(), vtNoProhibltedRanges.begin(), vtNoProhibltedRanges.end());
				}
				else {
					if (vtNoProhibltedRanges.empty())
					{
						if (m_LaneGeometryReference.geometryReferenceType == HDMapGeometryRangeReference::LaneGeometry)
						{
							ProhibitedRange range;
							range.prohibited = false;
							range.range.dRangeStartPos = 0;
							range.range.dRangeEndPos = 100;
							range.range.geometryReferenceType = HDMapGeometryRangeReference::LaneGeometry;
							vtNoProhibltedRanges.push_back(range);
						}
						else
						{
							ProhibitedRange range;
							range.prohibited = false;
							range.range.dRangeStartPos = m_LaneGeometryReference.dRangeStartPos * 100 / m_RoadLaneght;
							range.range.dRangeEndPos = m_LaneGeometryReference.dRangeEndPos * 100 / m_RoadLaneght;
							range.range.geometryReferenceType = HDMapGeometryRangeReference::RoadGeometry;
							vtNoProhibltedRanges.push_back(range);
						}
					}
					outVtRanges = vtNoProhibltedRanges;
				}
				std::sort(outVtRanges.begin(), outVtRanges.end(),
					[](const ProhibitedRange &a, const ProhibitedRange&b)->bool {
					return a.range.dRangeStartPos < b.range.dRangeStartPos;
				}
				);
				return bRet;
			}


			/**
			 *  @brief query whether the lane is associated with a stopline
			 *  @return true indicate the lane reference to a stopline
			 */
			bool GetHasStopLineMarking() const { return !m_vtStopLine.empty(); }

			/**
			 *  @brief query stopline id the lane associated
			 *  @return stop line info
			 */
			const std::vector<std::weak_ptr<HDMapExtendStopLine>> &GetStopLineMarking() const {return m_vtStopLine;}
			
			/**
			 *  @brief Get the turning type of the lane
			 *  @return turn type
			 */
			HDMapLaneMarkingDirection GetLaneMarkingDirection() const { return m_oLaneMarking; }

			/**
			 *  @brief get speed limit value
			 */
			const std::vector<std::shared_ptr<HDMapSpeedLimit>>& GetLaneSpeedLimit() const { return m_vtLaneSpeedLimit; }
			
			/**
			 *  @brief Get the type of the lane
			 *  @return turn lane type
			 */
			uint32_t GetLaneType() const { return m_nLaneType; }

			/**
			 *  @brief Get the transition type of the lane
			 *  @return transition lane type, map has more than one
			 */
			const std::vector<HDMapLaneTransitionInfo>&	GetLaneTransitionInfos() const { return m_vtLaneTransitions; }

			/**
			 *  @brief decide the lane is designation type or not  
			 *  @return true indicate the lane is the designation type from input parameter
			 */
			bool IsDesignationTypeOfLane(HDMapLaneType eType) const
			{
				uint32_t nLaneType = 1;
				uint16_t nOffset = static_cast<uint16_t>(eType);
				nLaneType = nLaneType << nOffset;
				if ( (nLaneType & m_nLaneType) == nLaneType){
					return true;
				}
				return false;
			}	
		private:
			bool InTimeRegion(const TimeRangeOfDay &timrRegion, TimeOfDay &curTime) const {
				if (timrRegion.endTime.hour == 0 && timrRegion.endTime.minute == 0)
				{
					TimeOfDay tmpTm = timrRegion.endTime;
					tmpTm.hour = 23;
					tmpTm.minute = 59;

					if (timrRegion.isInclusive) {
						return timrRegion.startTime <= curTime && curTime <= tmpTm;
					}
					else {
						return curTime < timrRegion.startTime || tmpTm < curTime;
					}
				}
				else
				{
					if (timrRegion.isInclusive) {
						return timrRegion.startTime <= curTime && curTime < timrRegion.endTime;
					}
					else {
						return curTime < timrRegion.startTime || timrRegion.endTime <= curTime;
					}
				}
			}
			bool isVehicle(const VehicleTypeSequence &condition, HDMapVehicleTypes vtype) const {
				return condition & (1 << vtype);
			}

			bool IsRestrict(HDMapVehicleTypes vtype, DayOfWeekBitPos curDay, TimeOfDay curTime, std::vector<ProhibitedRange>  &outVtRanges) const {
				auto getFullRange = [](const HDMapGeometryRangeReference &range, const double &roadLength)->ProhibitedRange {
					ProhibitedRange ret;
					ret.range.geometryReferenceType = range.geometryReferenceType;
					if (range.geometryReferenceType == HDMapGeometryRangeReference::RoadGeometry) {
						ret.range.dRangeStartPos = int(range.dRangeStartPos * 10000 / roadLength) / 100.0;
						ret.range.dRangeEndPos = int(range.dRangeEndPos * 10000 / roadLength) / 100.0;
					}
					else {
						ret.range.dRangeStartPos = 0;
						ret.range.dRangeEndPos = 100;
					}
					return ret;
				};

				bool bRet = false;
				for (auto &it : mVecAccessCondition) {
					if (!it.dateRangeOfYear_valid_flag)
						if (it.daysOfWeek_valid_flag) {
							if (it.daysOfWeek & 1 << curDay) {
								if (!it.timeRangeOfDay_valid_flag) {
									if (isVehicle(it.vehicleType, vtype)) {
										if (it.mProhibleRange.prohibited) {
											ProhibitedRange item = it.mProhibleRange;
											item.prohibited = true;
											outVtRanges.push_back(item);
											bRet = bRet || true;
										}
										else {
											ProhibitedRange item = getFullRange(m_LaneGeometryReference, m_RoadLaneght);
											item.prohibited = true;
											outVtRanges.push_back(item);
											return true;
										}
									}
									else {
										if (it.mProhibleRange.prohibited) {
											ProhibitedRange item = it.mProhibleRange;
											item.prohibited = false;
											outVtRanges.push_back(item);
											bRet = bRet || false;
										}
										else {
											ProhibitedRange item = getFullRange(m_LaneGeometryReference, m_RoadLaneght);
											item.prohibited = false;
											outVtRanges.push_back(item);
											return false;
										}
									}
								}
							}
						}
				}

				for (auto &it : mVecAccessCondition) {
					if (!it.dateRangeOfYear_valid_flag)
						if (it.daysOfWeek_valid_flag) {
							if (it.daysOfWeek & 1 << curDay) {
								if (it.timeRangeOfDay_valid_flag) {
									if (InTimeRegion(it.timeRangeOfDay, curTime)) {
										if (isVehicle(it.vehicleType, vtype)) {
											if (it.mProhibleRange.prohibited) {
												ProhibitedRange item = it.mProhibleRange;
												item.prohibited = true;
												outVtRanges.push_back(item);
												bRet = bRet || true;
											}
											else {
												ProhibitedRange item = getFullRange(m_LaneGeometryReference, m_RoadLaneght);
												item.prohibited = true;
												outVtRanges.push_back(item);
												return true;
											}
										}
										else {
											if (it.mProhibleRange.prohibited) {
												ProhibitedRange item = it.mProhibleRange;
												item.prohibited = false;
												outVtRanges.push_back(item);
												bRet = bRet || false;
											}
											else {
												ProhibitedRange item = getFullRange(m_LaneGeometryReference, m_RoadLaneght);
												item.prohibited = false;
												outVtRanges.push_back(item);
												return false;
											}
										}
									}
								}
							}
						}
				}
				for (auto &it : mVecAccessCondition) {
					if (!it.dateRangeOfYear_valid_flag)
						if (!it.daysOfWeek_valid_flag) {
							if (it.timeRangeOfDay_valid_flag) {
								if (InTimeRegion(it.timeRangeOfDay, curTime)) {
									if (isVehicle(it.vehicleType, vtype)) {
										if (it.mProhibleRange.prohibited) {
											ProhibitedRange item = it.mProhibleRange;
											item.prohibited = true;
											outVtRanges.push_back(item);
											bRet = bRet || true;
										}
										else {
											ProhibitedRange item = getFullRange(m_LaneGeometryReference, m_RoadLaneght);
											item.prohibited = true;
											outVtRanges.push_back(item);
											return true;
										}
									}
									else {
										if (it.mProhibleRange.prohibited) {
											ProhibitedRange item = it.mProhibleRange;
											item.prohibited = false;
											outVtRanges.push_back(item);
											bRet = bRet || false;
										}
										else {
											ProhibitedRange item = getFullRange(m_LaneGeometryReference, m_RoadLaneght);
											item.prohibited = false;
											outVtRanges.push_back(item);
											return false;
										}
									}
								}
							}
						}
				}
				for (auto &it : mVecAccessCondition) {
					if (!it.dateRangeOfYear_valid_flag)
						if (!it.daysOfWeek_valid_flag) {
							if (!it.timeRangeOfDay_valid_flag) {
								if (isVehicle(it.vehicleType, vtype)) {
									if (it.mProhibleRange.prohibited) {
										ProhibitedRange item = it.mProhibleRange;
										item.prohibited = true;
										outVtRanges.push_back(item);
										bRet = bRet || true;
									}
									else {
										ProhibitedRange item = getFullRange(m_LaneGeometryReference, m_RoadLaneght);
										item.prohibited = true;
										outVtRanges.push_back(item);
										return true;
									}
								}
								else {
									if (it.mProhibleRange.prohibited) {
										ProhibitedRange item = it.mProhibleRange;
										item.prohibited = false;
										outVtRanges.push_back(item);
										bRet = bRet || false;
									}
									else {
										ProhibitedRange item = getFullRange(m_LaneGeometryReference, m_RoadLaneght);
										item.prohibited = false;
										outVtRanges.push_back(item);
										return false;
									}
								}
							}
						}
				}
				return bRet;
			}

		public:
			
			/**
			 *  @brief conplex Restriction info
			 */
			struct HDMapLaneProhibitedCondition{
				uint8_t					mIsValid;						///< enable flag
				VehicleTypeSequence		vehicleType;					///< flag sequence for each vehicale type
				DaysOfWeek              daysOfWeek;						///< time range for day of week
				bool					daysOfWeek_valid_flag;			///< time range enable flag
				TimeRangeOfDay          timeRangeOfDay;					///< time range of one day
				bool					timeRangeOfDay_valid_flag;		///< time range of day enable flag
				DateRangeOfYear			dateRangeOfYear;				///< date range of one year
				bool					dateRangeOfYear_valid_flag;		///< date range of day enable flag
				ProhibitedRange			mProhibleRange;
			};

		private:
			friend class HDMapImpl;
			uint64_t											m_nID;						///< 
			uint32_t											m_nTileID;					///< 
			uint32_t											m_nWidth;					///< 
			uint16_t											m_nOrderNum;				///< 
			bool												m_bNonMotorizedLane;		///< 
			uint32_t											m_nLaneType;				///< 
			HDMapDirection										m_Direction;				///< 
			HDMapLaneMarkingDirection							m_oLaneMarking;				///< 
			HDMapLaneConnectivityElementType					m_ConnectivityElemType;		///< 
			std::weak_ptr<HDMapRoadInfo>						m_ptrRoad;					///< 
			std::weak_ptr<HDMapLaneGroupInfo>					m_ptrLaneGroup;				///< 
			std::weak_ptr<HDMapLaneInfo>						m_ptrRightLane;				///< 
			std::weak_ptr<HDMapLaneInfo>						m_ptrLeftLane;				///< 
			std::vector<std::weak_ptr<HDMapLaneInfo>>			m_vtOppositeLanes;			///< same link and opposite direction
			std::vector<std::shared_ptr<HDMapSpeedLimit>>		m_vtLaneSpeedLimit;			///< all speed limit of the lane
			std::vector<HDMapLaneWidthInfo>						m_vtPercentWidth;			///< 
			std::vector<Navinfo::Engine::Math::Vec3d>			m_vtGeometryPoints;			///< 
			std::vector<Navinfo::Engine::Math::LineSegment2d>	m_vtSegments;				///< 
			std::shared_ptr<HDMapLaneBoundariesInfo>			m_ptrRightLaneBoundaries;	///< one lane have two laneBoundaries
			std::shared_ptr<HDMapLaneBoundariesInfo>			m_ptrLeftLaneBoundaries;	///< 
			std::vector<std::shared_ptr<HDMapObjectInfo>>		m_vtPrimaryTrifficLight;	///< Primary TrafficLight object
			std::vector<std::shared_ptr<HDMapObjectInfo>>		m_vtAuxTrafficLight;		///< Aux TrafficLight object
			std::vector<std::weak_ptr<HDMapLaneInfo>>			m_vtSourceLanes;			///< source lane  through to current lane
			std::vector<std::weak_ptr<HDMapLaneInfo>>			m_vtDestinationLanes;		///< current lane go to destination lane
			std::vector<HDMapLaneProhibitedCondition>			mVecAccessCondition;		///< 
			std::vector<HDMapLaneTransitionInfo>				m_vtLaneTransitions;		///< 
			std::vector<std::weak_ptr<HDMapExtendStopLine>>		m_vtStopLine;				///< reference from stop line to traffic light
			HDMapGeometryRangeReference							m_LaneGeometryReference;	///< 
			double												m_RoadLaneght;
		};
	}
}

namespace Navinfo{
	namespace HDMap{
		typedef Navinfo::Engine::HDMapLaneInfo Lane;
	}
}